import pandas as pd
import re
import json
from zhipuai import ZhipuAI
from tenacity import retry, stop_after_attempt, wait_exponential
import jieba
from collections import Counter
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import logging
import sys
from datetime import datetime

# 配置日志记录（捕获控制台输出）
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(message)s',
    handlers=[
        logging.FileHandler('analysis_log.txt', encoding='utf-8'),
        logging.StreamHandler(sys.stdout)
    ]
)

# 配置中文字体显示[6,7](@ref)
plt.rcParams['font.sans-serif'] = ['SimHei']  # 设置黑体
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题


# 添加 智谱AI 的API密钥
client = ZhipuAI(api_key="1b412791085d4944866fe571f876fc96.a43ddOPPUypreN4U")
system_prompt = """
你是一个专业的汽车舆情分析师，需要完成以下任务：
1. 情感判断：根据文本内容判断情感倾向，返回【积极/消极/中立】
2. 主题分类：归类到以下标签中：
   - 安全缺陷（如电池、车门设计问题）
   - 公关危机（如回应速度、声明态度）
   - 用户情绪（如支持、愤怒）
   - 行业影响（如政策、股价波动）
3. 提取关键词：从文本中提取3个核心关键词，用逗号分隔

输出格式要求为JSON，例如：
{"sentiment": "消极", "topic": "安全缺陷", "keywords": "电池燃爆,车门解锁,救援延迟"}
"""


def clean_weibo_text(text):
    """深度清洗微博文本"""
    if not isinstance(text, str):
        return ""

    # 初始化cleaned变量
    cleaned_text = text

    # 清洗规则
    cleaned_text = re.sub(r'L\S+的微博视频', '', cleaned_text)  # 去除视频链接
    cleaned_text = re.sub(r'#([^#]+)#', '', cleaned_text)      # 去除话题标签
    cleaned_text = re.sub(r'http\S+', '', cleaned_text)         # 去除URL
    cleaned_text = re.sub(r'展开c|收起d', '', cleaned_text)     # 去除控件符号
    cleaned_text = re.sub(r'\u200b|\xa0|\n', ' ', cleaned_text) # 去除特殊空白符

    # 提取中文核心内容
    cleaned = re.findall(r'[\u4e00-\u9fa5，。！？、；：～\d]+', cleaned_text)
    return ' '.join(cleaned)[:500] if cleaned else ""  # 返回处理后的文本

@retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=4, max=10))
def safe_analyze(text):
    """带安全机制的API调用"""
    try:
        response = client.chat.completions.create(
            model="glm-4",
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": f"分析文本：{text}"}
            ],
            temperature=0.2,
            max_tokens=200
        )
        result = response.choices[0].message.content

        # 记录成功响应
        logging.info(f"分析结果：{result}")
        return json.loads(result)

    except json.JSONDecodeError:
        error_msg = f"JSON解析失败的原始响应：{result}"
        logging.error(error_msg)  # 记录错误信息到日志文件
        return {"sentiment": "Error", "topic": "Error", "keywords": ""}
    except Exception as e:
        error_msg = f"API调用异常：{str(e)}"
        logging.error(error_msg)
        return {"sentiment": "Error", "topic": "Error", "keywords": ""}


# 数据加载与清洗
df = pd.read_excel("微博搜索关键词采集.xlsx")
df['清洗文本'] = df['博文内容'].apply(clean_weibo_text)
df = df[df['清洗文本'].str.len() > 10]

# 分批处理（添加日志记录）
batch_size = 20
results = []
for i in range(0, len(df), batch_size):
    batch = df.iloc[i:i + batch_size]
    logging.info(f"\n{'=' * 40} 开始处理批次 {i // batch_size + 1} {'=' * 40}")

    batch_results = []
    for idx, row in batch.iterrows():
        result = safe_analyze(row['清洗文本'])
        batch_results.append(result)
        logging.info(f"已处理第{idx}条数据")

    results.extend(batch_results)
    pd.DataFrame(results).to_excel("舆情分析_进度备份.xlsx", index=False)

# 合并结果
final_df = pd.concat([df.reset_index(drop=True), pd.DataFrame(results)], axis=1)
final_df.to_excel("final_analysis_with_clean.xlsx", index=False)


# -------------------- 可视化分析模块 --------------------
# -------------------- 可视化分析模块 --------------------
def visualize_analysis():
    # 读取日志文件
    with open('analysis_log.txt', 'r', encoding='utf-8') as f:
        log_content = f.read()

    # 修改点1：精准提取关键词字段内容（避免包含JSON标签）
    analysis_texts = re.findall(r'"keywords": "(.*?)"', log_content)  # 只提取关键词部分

    # 修改点2：增强停用词过滤机制
    stopwords = ["的", "是", "在", "了", "和", "等", "问题", "需要", "可能", "如果"]
    exclude_terms = ['json', 'sentiment', 'topic', 'keywords', 'Error']  # 新增排除词

    # 修改点3：双重过滤机制
    words = [
        word for text in analysis_texts
        for word in jieba.lcut(text.replace(',', ' '))  # 处理逗号分隔符
        if len(word) > 1
           and word not in stopwords
           and word not in exclude_terms
           and not re.match(r'^[\d\W]+$', word)  # 排除纯数字和符号组合
    ]

    # 生成词云（保持原有参数）
    plt.figure(figsize=(15, 8))
    wordcloud = WordCloud(
        font_path='msyh.ttc',
        background_color='white',
        width=1200,
        height=800,
        collocations=False  # 新增：防止重复词[5](@ref)
    ).generate(' '.join(words))

    plt.imshow(wordcloud, interpolation='bilinear')
    plt.axis('off')
    plt.title('舆情分析高频词云', fontsize=20, pad=20)
    plt.savefig('wordcloud.png', dpi=300, bbox_inches='tight')
    plt.show()

    # 生成条形图（过滤后数据）
    word_counts = Counter(words).most_common(15)
    plt.figure(figsize=(12, 6))
    plt.barh([w[0] for w in word_counts],
             [w[1] for w in word_counts],
             color='#2c7fb8')
    plt.xlabel('出现频次', fontsize=12)
    plt.title('TOP15高频关键词分布', fontsize=16)
    plt.gca().invert_yaxis()
    plt.grid(axis='x', linestyle='--', alpha=0.6)
    plt.tight_layout()
    plt.savefig('word_frequency.png', dpi=300)
    plt.show()

    # 修改点4：增强时间数据处理
    if '发布时间' in final_df.columns:
        # 转换日期时增加错误处理
        final_df['发布时间'] = pd.to_datetime(
            final_df['发布时间'],
            format='%m月%d日 %H:%M',
            errors='coerce'  # 无效日期转为NaT[6](@ref)
        )
        # 过滤无效日期
        valid_dates = final_df.dropna(subset=['发布时间'])

        # 生成时间序列
        time_series = valid_dates.resample('D', on='发布时间').size()

        # 可视化优化
        plt.figure(figsize=(12, 6))
        time_series.plot(kind='line',
                         marker='o',
                         color='#d62728',
                         linewidth=2,  # 加粗趋势线
                         markersize=8)  # 增大标记点
        plt.title('舆情分析时间趋势', fontsize=16)
        plt.xlabel('日期', fontsize=12)
        plt.ylabel('分析数量', fontsize=12)
        plt.grid(True, alpha=0.3)
        plt.xticks(rotation=45)  # 倾斜日期标签
        plt.tight_layout()
        plt.savefig('time_series.png', dpi=300)
        plt.show()


# 执行可视化
visualize_analysis()
print("可视化图表已保存为：wordcloud.png, word_frequency.png, time_series.png")